echo '============================================================'
}
+op_start () {
+ if [ "${bridge}" == "null" ] ; then
+ return
+ fi
+ # Create the bridge and give it the interface IP addresses.
+ # Move the interface routes onto the bridge.
+ create_bridge ${netdev} ${bridge}
+ transfer_addrs ${netdev} ${bridge}
+ transfer_routes ${netdev} ${bridge}
+ # Don't add $dev to $bridge if it's already on a bridge.
+ if ! brctl show | grep -q ${netdev} ; then
+ brctl addif ${bridge} ${netdev}
+ fi
+
+ if [ ${antispoof} == 'yes' ] ; then
+ antispoofing ${netdev} ${bridge}
+ fi
+}
+
+op_stop () {
+ if [ "${bridge}" == "null" ] ; then
+ return
+ fi
+ # Remove the interface from the bridge.
+ # Move the routes back to the interface.
+ brctl delif ${bridge} ${netdev}
+ transfer_routes ${bridge} ${netdev}
+
+ # It's not our place to be enabling forwarding...
+}
+
case ${OP} in
start)
- # Create the bridge and give it the interface IP addresses.
- # Move the interface routes onto the bridge.
- create_bridge ${netdev} ${bridge}
- transfer_addrs ${netdev} ${bridge}
- transfer_routes ${netdev} ${bridge}
- # Don't add $dev to $bridge if it's already on a bridge.
- if ! brctl show | grep -q ${netdev} ; then
- brctl addif ${bridge} ${netdev}
- fi
-
- if [ ${antispoof} == 'yes' ] ; then
- antispoofing ${netdev} ${bridge}
- fi
-
+ op_start
;;
stop)
- # Remove the interface from the bridge.
- # Move the routes back to the interface.
- brctl delif ${bridge} ${netdev}
- transfer_routes ${bridge} ${netdev}
-
- # It's not our place to be enabling forwarding...
+ op_stop
;;
status)
;;
esac
+# Don't do anything if the bridge is "null".
+if [ "${bridge}" == "null" ] ; then
+ exit
+fi
+
# Add/remove vif to/from bridge.
brctl ${brcmd} ${bridge} ${vif}
'type' : type,
'idx' : idx })
+ def xend_domain_device_configure(self, id, config, idx):
+ return self.xendPost(self.domainurl(id),
+ {'op' : 'device_configure',
+ 'idx' : idx,
+ 'config' : fileof(config) })
+
def xend_consoles(self):
return self.xendGet(self.consoleurl())
self.update_domain(dominfo.id)
return val
+ def domain_device_configure(self, id, devconfig, idx):
+ """Configure an existing device for a domain.
+
+ @param id: domain id
+ @param devconfig: device configuration
+ @param idx: device index
+ @return: updated device configuration
+ """
+ dominfo = self.domain_lookup(id)
+ self.refresh_schedule()
+ val = dominfo.device_configure(devconfig, idx)
+ self.update_domain(dominfo.id)
+ return val
+
+
def domain_device_destroy(self, id, type, idx):
"""Destroy a device.
@param id: domain id
- @param type: device type
@param idx: device index
+ @param type: device type
"""
dominfo = self.domain_lookup(id)
self.refresh_schedule()
"""
dominfo = self.domain_lookup(id)
devs = dominfo.get_devices(type)
- #return range(0, len(devs))
return devs
def domain_devtype_get(self, id, type, idx):
d = dev_handler(self, dev_config, dev_index, change=1)
return d
+ def device_configure(self, dev_config, idx):
+ """Configure an existing device.
+
+ @param dev_config: device configuration
+ @param idx: device index
+ """
+ type = sxp.name(dev_config)
+ dev = self.get_device_by_index(type, idx)
+ if not dev:
+ raise VmError('invalid device: %s %s' % (type, idx))
+ new_config = dev.configure(dev_config, change=1)
+ devs = self.devices.get(type)
+ index = devs.index(dev)
+ # Patch new config into device configs.
+ dev_configs = self.config_devices(type)
+ old_config = dev_configs[index]
+ dev_configs[index] = new_config
+ # Patch new config into vm config.
+ new_full_config = ['device', new_config]
+ old_full_config = ['device', old_config]
+ old_index = self.config.index(old_full_config)
+ self.config[old_index] = new_full_config
+ return new_config
+
def device_destroy(self, type, idx):
"""Destroy a device.
val = fn(req.args, {'dom': self.dom.id})
return val
+ def op_device_configure(self, op, req):
+ fn = FormFn(self.xd.domain_device_configure,
+ [['dom', 'str'],
+ ['config', 'sxpr'],
+ ['idx', 'str']])
+ d = fn(req.args, {'dom': self.dom.id})
+ return d
+
def op_vifs(self, op, req):
devs = self.xd.domain_vif_ls(self.dom.id)
return [ dev.sxpr() for dev in devs ]
"""
raise NotImplementedError()
+ def configure(self, config, change=0):
+ raise NotImplementedError()
+
class SplitDev(Dev):
def __init__(self, idx, controller):
self.evtchn = None
self.configure(config)
- def configure(self, config):
+ def _get_config_mac(self, config):
+ vmac = sxp.child_value(config, 'mac')
+ if not vmac: return None
+ mac = [ int(x, 16) for x in vmac.split(':') ]
+ if len(mac) != 6: raise XendError("invalid mac")
+ return mac
+
+ def _get_config_ipaddr(self, config):
+ ips = sxp.children(config, elt='ip')
+ if ips:
+ val = []
+ for ipaddr in ips:
+ val.append(sxp.child0(ipaddr))
+ else:
+ val = None
+ return val
+
+ def configure(self, config, change=0):
+ if change:
+ return self.reconfigure(config)
self.config = config
self.mac = None
self.bridge = None
self.script = None
self.ipaddr = []
-
- vmac = sxp.child_value(config, 'mac')
- if not vmac: raise XendError("invalid mac")
- mac = [ int(x, 16) for x in vmac.split(':') ]
- if len(mac) != 6: raise XendError("invalid mac")
- self.mac = mac
+ mac = self._get_config_mac(config)
+ if mac is None:
+ raise XendError("invalid mac")
+ self.mac = mac
self.bridge = sxp.child_value(config, 'bridge')
self.script = sxp.child_value(config, 'script')
-
- ipaddrs = sxp.children(config, elt='ip')
- for ipaddr in ipaddrs:
- self.ipaddr.append(sxp.child0(ipaddr))
+ self.ipaddr = self._get_config_ipaddr(config) or []
try:
self.backendDomain = int(sxp.child_value(config, 'backend', '0'))
except:
raise XendError('invalid backend domain')
+ def reconfigure(self, config):
+ """Reconfigure the interface with new values.
+ Not all configuration parameters can be changed:
+ bridge, script and ip addresses can,
+ backend and mac cannot.
+
+ To leave a parameter unchanged, omit it from the changes.
+
+ @param config configuration changes
+ @return updated interface configuration
+ @raise XendError on errors
+ """
+ changes = {}
+ mac = self._get_config_mac(config)
+ bridge = sxp.child_value(config, 'bridge')
+ script = sxp.child_value(config, 'script')
+ ipaddr = self._get_config_ipaddr(config)
+ backendDomain = sxp.child_value(config, 'backend', '0')
+ if (mac is not None) and (mac != self.mac):
+ raise XendError("cannot change mac")
+ if (backendDomain is not None) and (backendDomain != str(self.backendDomain)):
+ raise XendError("cannot change backend")
+ if (bridge is not None) and (bridge != self.bridge):
+ changes['bridge'] = bridge
+ if (script is not None) and (script != self.script):
+ changes['script'] = script
+ if (ipaddr is not None) and (ipaddr != self.ipaddr):
+ changes['ipaddr'] = ipaddr
+
+ if changes:
+ self.vifctl("down")
+ for (k, v) in changes.items():
+ setattr(self, k, v)
+ self.config = sxp.merge(config, self.config)
+ self.vifctl("up")
+ return self.config
+
def sxpr(self):
vif = str(self.vif)
mac = self.get_mac()
"has_id",
"with_id",
"child_with_id",
- "elements",
+ "elements",
+ "merge",
"to_string",
"from_string",
"all_from_string",
yield v
i += 1
+def merge(s1, s2):
+ """Merge sxprs s1 and s2.
+ Returns an sxpr containing all the fields from s1 and s2, with
+ entries in s1 overriding s2. Recursively merges fields.
+
+ @param s1 sxpr
+ @param s2 sxpr
+ @return merged sxpr
+ """
+ if s1 is None:
+ val = s2
+ elif s2 is None:
+ val = s1
+ elif elementp(s1):
+ name1 = name(s1)
+ (m1, v1) = child_map(s1)
+ (m2, v2) = child_map(s2)
+ val = [name1]
+ for (k1, f1) in m1.items():
+ merge_list(val, f1, m2.get(k1, []))
+ for (k2, f2) in m2.items():
+ if k2 in m1: continue
+ val.extend(f2)
+ val.extend(v1)
+ else:
+ val = s1
+ return val
+
+def merge_list(sxpr, l1, l2):
+ """Merge element lists l1 and l2 into sxpr.
+ The lists l1 and l2 are all element with the same name.
+ Values from l1 are merged with values in l2 and stored in sxpr.
+ If one list is longer than the other the excess values are used
+ as they are.
+
+ @param sxpr to merge into
+ @param l1 sxpr list
+ @param l2 sxpr list
+ @return modified sxpr
+ """
+ n1 = len(l1)
+ n2 = len(l2)
+ nmin = min(n1, n2)
+ for i in range(0, nmin):
+ sxpr.append(merge(l1[i], l2[i]))
+ for i in range(nmin, n1):
+ sxpr.append(l1[i])
+ for i in range(nmin, n2):
+ sxpr.append(l2[i])
+ return sxpr
+
+def child_map(sxpr):
+ """Get a dict of the elements in sxpr and a list of its values.
+ The dict maps element name to the list of elements with that name,
+ and the list is the non-element children.
+
+ @param sxpr
+ @return (dict, list)
+ """
+ m = {}
+ v = []
+ for x in children(sxpr):
+ if elementp(x):
+ n = name(x)
+ l = m.get(n, [])
+ l.append(x)
+ m[n] = l
+ else:
+ v.append(x)
+ return (m, v)
+
def to_string(sxpr):
"""Convert an sxpr to a string.